/**
 * @author wn
 * @date 2023/07/26 10:14:15
 * @description:uniapp 笔记
 */

/*
1 安全区域
屏幕去掉 状态栏 +刘海 剩余展示内容的区域 --
可通过 uni.getSystemInfoSync() 获取屏幕 上边界 到安全区 顶部 的距离。
safeAreaInsets = {top: 59, left: 0, right: 0, bottom: 34}

"navigationStyle": "custom", // 隐藏默认导航,自定义
页面 直接顶到 windows 最上方

这时 paddingTop:安全距离
view 中的 内容就不会被遮挡

const { safeAreaInsets } = uni.getSystemInfoSync()
const top = ref<number | undefined>()
top.value = safeAreaInsets?.top

:style="{ paddingTop: top + 'px' }"

自定义状态栏 返回按钮 --可以使用 navigator + icon 自定义图标
                            open-type="navigateBack" 对应 uni.navigateBack 设置 路由

2 icon  使用 iconFont

3 font-size 有继承size时  可以指定 百分比
  font-size: 80%;

4 伪元素  可以通过 display:flex; 与 text的内容 排列
  .caption {
	display: flex;
	justify-content: center;
	align-items: center;
	&::before,
	&::after {
		content: '';
		width: 20rpx;
		height: 20rpx;
		background: url(@/static/images/bubble.png) center/contain;
	}
}

5 uniAPP css  使用 标签选择器 报警告  要避免

6 v-if 导致 setup 执行了两次
  v-show 不会 onMounted中也不会

7  注意  page { height: 100%; }
  基于 scroll-view 组件实现 下拉刷新 上拉加载
  配置 refresher-enabled     属性，开启自定义下拉刷新交互
  监听  @refresherrefresh    事件，判断用户是否执行了下拉操作
  配置  refresher-triggered  属性，是否关闭下拉状态  true 开始动画 false 关闭动画
  配置  @scrolltolower       滚动到底部/右边，会触发  事件 -- 上拉加载

8 生成骨架屏
  微信开发者工具 --左边页面 右下角--三个点--生成骨架屏
  --xxx.skeleton.wxml 和 xxx.skeleton.wxss--
  将二者封装成 xxx.skeleton.vue组件  这里生成的是整个页面的骨架屏
  要是只需要部分 比如 navBar 不需要  template 中 删除 结构即可

  <XXXSkeleton v-if="isLoading" />
  <template v-else>
    <xxx1.vue />
    <xxx2.vue />
  </template>

9 navigator 参数传递
  navigator 通过url传递的参数  会在 page 的 props中接收到
  传递的参数应该是基本类型（如字符串、数字等），或者是经过JSON序列化的对象
  <navigator
  :url="'/pages/navigate/navigate?item='+ encodeURIComponent(JSON.stringify(item))">

  const { item } = defineProps<{ item:string }>()
  const obj = JSON.parse(decodeURIComponent(item))

  自定义状态栏

10 小程序的 tap 事件  等同于 click

11 setup 的执行时机 在 onLoad 之前
   setup > onLoad > beforeCreated

12 uni-popup 弹出层组件
  插入内容  uni-popup-message   uni-popup-dialog  uni-popup-share
  uni-popup 组件实例 通过 open close 打开与关闭

  const popupRef = ref<{
  open: (type?: UniHelper.UniPopupType) => void
  close: () => void
}>()
  popup.value?.open("top")
  popup.value?.close()

  禁止滚动穿透

13 微信登录  获取微信用户基本信息（昵称、性别、手机号码等）
   用户在使用小程序时，其实已登录微信，其本质上就是：微信授权给小程序读取微信用户信息
   1 前端：调用 wx.login() 接口获取登录凭证（code）
     后端：通过凭证（code）向微信服务器生成 用户登录态
     用户登录态，不包含用户昵称、性别、手机号码等信息，作用是用于后端与微信服务器通讯
     onLoad-->
     const { code } = await wx.login()

   2 微信登录接口(后台 API)
   button -- open-type="getPhoneNumber"
   点击 弹窗--允许后
   触发 @getphonenumber 回调中 获取 -- LoginParams
     type LoginParams = {
       code: string
       encryptedData: string
       iv: string
      }

   回调中 -- 调用 后台 API -- 获取 -- LoginResult

export type LoginResult = {
  id: number // 用户ID
  avatar: string // 头像
  account: string // 账户名
  nickname?: string // 昵称
  mobile: string // 手机号
  token: string // 登录凭证
}

14 pages.json -- "navigationBarTextStyle": "white"
   导航栏标题-文字颜色  还可以设置当前页面 状态栏 电池,时间等文字颜色
   仅支持 black/white

15 分包 1 按模块管理页面，方便项目维护。
       2 减少主包体积，用到的时候再加载分包，属于性能优化解决方案
   通过 插件 uni-create-view 可以快速新建分包页面，自动配置分包路由。
   注意: 自动生成的分包页面 需要修改下 分包加载规则 的 路径
   subPackages--[]

   分包预下载 -- preloadRule
   当用户进入【某个】页面时，由框架自动预下载 分包，提升进入后续分包页面时的启动速度

16 表单校验 -- uni-forms -- uni-forms-item
   1 表单校验 2 自定义校验规则 3 动态表单校验 -- v-model的巧妙赋值 (name:value)
   触发时机 validate-trigger= "bind" -- 数据改变时
           blur--input失去焦点  submit 提交数据时

17 滑动删除 uni-swipe-action--uni-swipe-action-item
   可以通过 1 数据 2 插槽 -- 生成 左右滑块内容
   点击滑块触发 click 事件 -- 只对1数据渲染生效
           2插槽渲染的  通过插槽自身的点击事件触发 @tap
   滑块 开关  触发 change 事件

18 SKU 组件 -- gitee 中 源码中  components--下载  导入自己项目中  components
   组件市场 下载 组件 按照文档使用
    <vk-data-goods-sku-popup
      ref="skuPopup"
      v-model="skuKey"          true为打开组件，false为关闭组件
      border-radius="20"        顶部圆角值
      :localdata="goodsInfo"    数据源
      :mode="skuMode"           1:都显示 2:只显示购物车 3:只显示立即购买
      @open="onOpenSkuPopup"    打开组件时
      @close="SkuPopup"         关闭组件时
      @add-cart="addCart"       加到购物车时--选完SKU才会触发	selectShop 当前选择的sku数据
      @buy-now="buyNow"         立即购买时--选完SKU才会触发	selectShop 当前选择的sku数据
    ></vk-data-goods-sku-popup>
    还可以通过 属性 配置
    最大最小购买数量 点击步长 库存显隐 主题  右上角关闭按钮及样式  立即购买与加入购物车 文字内容 样式 背景
    商品缩略图背景  按钮可点不可点 样式

    localdata -- 数据格式
    数据定义重点看
    (sku_list--sku_name_arr) --> (spec_list)

   {
     "_id":"001",         // 商品ID
     "name": "iphone11",  // 商品名称
     "goods_thumb":"",    // 商品头像
     // 该商品对应的sku列表 -- 也就是最终的 选完规格后的 库存商品
    "sku_list": [
        {
      "_id": "001",           // SKU ID
      "goods_id": "001",      // 商品ID
      "goods_name": "xx",     // 商品名称
      "image": ""             // SKU头像
      "price": 19800,         // SKU 价格
      "stock": 100            // 库存
      // 该SKU由哪些规格组成（规格是有顺序的，需要与spec_list的数组顺序对应）
      "sku_name_arr": ["红色", "128G", "公开版"],
        }
    ],
     // 商品规格列表
    "spec_list": [
        {
            "name": "颜色", // 第一组规格名
            // 第一组规格的 第一项规格值名称    二项规格值名称  三项规格值名称
            "list": [{"name": "红色"},{"name": "黑色"},{"name": "白色"}]
        },
        {
            "name": "内存",
            "list": [{"name": "128G"},{"name": "256G"}]
        },
        {
            "name": "版本",
            "list": [{"name": "公开版"},{"name": "非公开版"}]
        }
    ]
}
sku_name_arr 数组的第一个值sku_name_arr[0] = spec_list[0].list中的任意一个元素的name属性的值
                               spec_list[0].list中必须要有且只有一个元素的name属性的值为"红色"

19 组件类型生命
 1 自定义组件   --   custom.vue
 2 组件类型     --   import custom from '@/components/custom.vue'
                    typeof custom
 3 组件实例     --   InstanceType<typeof custom>

 方式二
 1 import type { Component } from '@uni-helper/uni-app-types'
 2 定义 props  -- interface CustomProps {
                   name:string
                  }
 3 Component<T> 等同于  typeof T
   Component<CustomProps> === typeof custom
 4 组件实例     --   InstanceType<Component<CustomProps>>

最后 -- 全局组件类型声明--这样自定义的组件就有类型了
declare module 'vue' {
	export interface GlobalComponents {
		'custom': typeof custom
    'custom2': Component<CustomProps>
	}
}

20 滚动驱动的动画 -- this.animate(selector, keyframes, duration, ScrollTimeline)
    this.animate(
    '.avatar', // 选择器 多个空格隔开

    [{
    borderRadius: '0',
    borderColor: 'red',
    transform: 'scale(1) translateY(-20px)',
    offset: 0,
  }, {
    borderRadius: '25%',
    borderColor: 'blue',
    transform: 'scale(.65) translateY(-20px)',
    offset: .5,
  }],

    2000,

    {
    scrollSource: '#scroller', // 以谁滚动触发动画
    timeRange: 2000,
    startScrollOffset: 0,
    endScrollOffset: 85,
  })

  纯 CSS 实现
  https://segmentfault.com/a/1190000044039882#item-5

21 开发环境 -- boolean
   import.meta.env.DEV      开发
   import.meta.env.PROD     发布

22 微信支付 -- 获取微信支付参数 + 发起微信支付
   const onOrderPay = async () => {
	// 开发环境 DEV
	if (import.meta.env.DEV) {
		// 开发环境 -- 模拟支付
		await getPayMockApi({ orderId: id })
	} else {
		// 正式环境支付 -- 1.获取支付订单信息，
		const res = await getWxPayApi({ orderId: id })

		// uni.requestPayment(res) -- res:UniApp.RequestPaymentOptions
		// 2.调用微信支付API -- 弹框输密码
		await wx.requestPayment(res)
	}


 ===========================项目打包============================

 ======微信小程序端========
 1 运行打包命令 pnpm build:mp-weixin -- vsCode
 2 预览和测试，微信开发者工具导入生成的 /dist/build/mp-weixin 目录 -- 微信开发者工具
 3 上传小程序代码 -- 微信开发者工具 -- 上传
 4 提交审核和发布 -- 微信公众平台 -- 版本管理 -- 提交审核
 打包成其他小程序端的步骤类似，只是更换了 打包命令 和 开发者工具 。

 =======H5 端============
 1 运行打包命令 pnpm build:h5 -- vsCode
 2 预览和测试，使用浏览器打开 /dist/build/h5 目录下的 index.html 文件
 3 由运维部署到服务器
  // manifest.json
{
   // 网页端特有配置
  "h5": {
    "router": {
      "base": "./"   // 基础路径：./ 为相对路径
    }
  }
}

======打包为 APP 端=======
HBuilderX
1 手机预览与调试
2 导入HBuilderX-->选中项目根目录-->运行(运行到手机或模拟器)-->下载真机运行插件-->运行到Android App基座

打包APP -- 云打包
1 Manifest 中 获取 DCloud AppId
2 发行(原生APP 云打包)-->注册 DCloud 账号--> 登陆 DCloud-->
3 发行(原生APP 云打包)
使用云端证书(详情中  DCloud AppId -- 获取证书 -- Android 云端证书--创建证书)
正式打包
传统打包 或者 快速安心打包
打包
安装云打包插件
打包

======打包为 IOS 端=======
HBuilderX + MacBook + iphone
1 手机预览与调试
2 导入HBuilderX-->选中项目根目录-->运行(运行到手机或模拟器)-->运行到 IOS App基座
建议运行到模拟器上 真机版本太多了
mac 安装  Xcode  提供 iPhone 模拟器
运行 到 IOS App基座 时就会有 多个版本的 模拟器

打包IOS -- 云打包
需要 ios IDP/IEP 证书 -- 申请 每年几百元

证书私钥密码
证书profile文件
私钥证书

花钱就有了
其他按步骤进行填写

正式打包
传统打包 或者 快速安心打包
打包


====================================
各平台兼容
1 小程序端 不支持 * 选择器
  运行直接报错 --> 并集选择器 view,text,image{ }

2 页面视口差异 page
  H5端 -- 整个页面都是 视口 (上下 通过定位画出)
  小程序端 + APP端 -- 顶部导航栏 + 视口(webview区域) + 底部 tabBar
  (非tabBar页 或 者自定义导航栏 -->视口webview区域会相应延伸)

  A 视口内容 -- 是否 会被 上下 遮挡 (H5端)
  page {
	height: 100% !important;
 }
因为内部的继承关系  100% 可以让 H5的视口--page 在 中间,不会被上下部分因为定位遮挡
 B 定位 组件的位置 -- 是否 会被 上下 遮挡 (H5端)
 --window-bottom  App 小程序 都是 0 ,H5 tabBar高度
 --window-top     App 小程序 都是 0 ,H5 导航栏高度
 position:fixed;
 bottom:var(--window-bottom);

3 H5 style 默认开启 scoped
 开发者工具生成的 骨架屏 是根据页面样式 + 其他样式生成的
 打包到 H5 或者 APP 后
 因为 默认开启了 scoped
 骨架屏 依赖的 一些组件样式  比如 首页(轮播图,分类,猜你喜欢) 的样式引用不到
 骨架屏 样式 异常
将 scss 写到独立的  category.scss ,hot.scss 中
组件 和 骨架屏 style 中 分别引用
骨架屏中
#ifdef H5 || APP-PLUS

@import '../styles/category.scss';
@import '../styles/hot.scss';

#endif

4 组件兼容
编译到不同的平台时  相同的组件可能会 编译成 不同的 组件树
例如 navigator --> a
标签 与 结构 父子嵌套 都会变化 --导致样式 失效 -- flex失效  类名丢失 等
根据平台 通过条件编译调整 css 样式 即可

5 js 的 跨端 条件编译 -- 根据文档查阅即可
微信支付
选择图片

/


























































































































































*/
